import { ElMessage } from 'element-plus'
import QRCode from 'qrcode'
import { saveAs } from 'file-saver'

interface CheckCondition {
  format?: string[] // ['image/jpeg', 'image/jpg', 'image/png']
  // 使用 M 为单位
  size?: number
}
type ErrorType = 'size' | 'format' | null

// 标准的上传之前检测方法 和 业务中的提示拆分  可以用于以后不同需求不同业务场景的扩展
export function beforeUploadCheck(file: File, condition: CheckCondition) {
  const { format, size } = condition
  const isValidFormat = format ? format.includes(file.type) : true
  const isValidSize = size ? file.size / 1024 / 1024 < size : true
  let error: ErrorType = null
  if (!isValidFormat) {
    error = 'format'
  }
  if (!isValidSize) {
    error = 'size'
  }

  return {
    passed: isValidFormat && isValidSize,
    error
  }
}

// 自定义格式校验和错误提示
export function commonUploadCheck(file: File) {
  const { passed, error } = beforeUploadCheck(file, { format: ['image/jpeg', 'image/jpg', 'image/png'], size: 1 })
  if (error === 'format') {
    ElMessage.error('上传图片只能是 JPG/PNG 格式!')
  }
  if (error === 'size') {
    ElMessage.error('上传图片大小不能超过 1Mb')
  }
  return passed
}

export function getImageDimensions(url: string | File) {
  return new Promise<{ width: number; height: number }>((resolve, reject) => {
    const image = new Image()
    image.src = typeof url === 'string' ? url : URL.createObjectURL(url)
    image.addEventListener('load', () => {
      const { naturalWidth: width, naturalHeight: height } = image
      resolve({ width, height })
    })
    image.addEventListener('error', () => {
      reject(new Error('图片加载出现问题'))
    })
  })
}

// 循环查找父级节点: 查看当前节点的 parentNode 是否有 className
export function getParentElement(element: HTMLElement, className: string) {
  while (element) {
    if (element.classList && element.classList.contains(className)) {
      return element
    } else {
      element = element.parentNode as HTMLElement
    }
  }
  return null
}

export function insertAt(arr: any[], index: number, newItem: any) {
  return [...arr.slice(0, index), newItem, ...arr.slice(index)]
}

// 生成二维码
export function generateQRCode(elementId: string, url: string, width = 100) {
  const el = document.getElementById(elementId) as HTMLCanvasElement
  return QRCode.toCanvas(el, url, { width })
}

export function downloadFile(src: string, fileName = 'default.png') {
  const link = document.createElement('a')
  link.download = fileName
  link.rel = 'noopener'
  link.href = src
  link.dispatchEvent(new MouseEvent('click'))
}

export function downloadImage(url: string) {
  const fileName = url.substring(url.lastIndexOf('/') + 1)
  saveAs(url, fileName)
}

export function timeout(ms: number) {
  return new Promise(resolve => setTimeout(resolve, ms))
}

/**
 * 防抖
 */
export function debounce(fn: (...args: any[]) => void, delay = 300) {
  let timer: any = null
  return function (this: any, ...args: any[]) {
    // const args = Array.prototype.slice.call(arguments)
    if (timer) {
      clearTimeout(timer)
    }
    timer = setTimeout(() => {
      fn.apply(this, args)
      timer = null
    }, delay)
  }
}

/**
 * 节流
 */
export function throttle(fn: (...args: any[]) => void, delay = 300) {
  let timer: any = null
  return function (this: any, ...args: any[]) {
    if (timer) {
      return
    }
    timer = setTimeout(() => {
      timer = null
      fn.apply(this, args)
    }, delay)
  }
}

/**
 * HTMLElement 添加 class
 * @param el DOM
 * @param className class样式
 */
export function addClass(el: HTMLElement, className: string) {
  if (!el.classList.contains(className)) {
    el.classList.add(className)
  }
}

/**
 * HTMLElement 删除 class
 * @param el DOM
 * @param className class样式
 */
export function removeClass(el: HTMLElement, className: string) {
  el.classList.remove(className)
}
